#pragma once

#include <core/strings/string_util.h>

#include <algorithm>
#include <list>
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <vector>

#include "bondlib.h"
/*
[内存优化][scofined.qi]
发行人内存编码优化
原始发行人信息的结构体QBISSUERINFO的每个字段都定义的足够大
且有很多空间,且都是字符串数组成员

StringArray,如其名,是一种简单的编码,将每个成员的实
际内容紧凑的编码到一起,然后在前面放置一个每个字段
的偏移量数组访问的时候,通过成员序号来获取每个成员
的偏移量进而获取每个成员的实际字符串内容

优化数据:
StringArray优化:
主键优化:使用KeyString替换std::string,缩减一半的内存
*/
typedef std::vector<qb::base::strinfo> StringOffsets;
enum class kIssuerInfo : unsigned char {
  Institution_Code,
  Full_Name_C,
  Issuer_Type,
  SW_Sector_Code,
  SW_Subsector_Code,
  SW_2021_Sector_Code,
  SW_2021_Subsector_Code,
  Province_Code,
  Short_Name_C,
  Full_Name_E,
  Short_Name_E,
  Listed_Type,
  Actual_Controller_Name,
  Actual_Controller_Type,
  Rate,
  CBRC_Financing_Platform,
  Municipal_code,
  Issuer_tag,
  Field_Count
};

class S_BONDLIB_EXPORT StringArray {
  typedef unsigned char uchar;
  typedef unsigned short ushort;
  const ushort m_flag : 1;
  const ushort m_count : 15;
  //  uchar   offsets[count];	// 当falg为0的时候
  //  ushort  offsets[count]; // 当flag为1的时候
  //  紧跟着指定个数的字符串,每个都以0结尾,偏移量从此开始计算

 private:
  StringArray(ushort flag, ushort count) : m_flag(flag), m_count(count) {}

 public:
  ~StringArray() {}
  static void Destroy(StringArray* sarray);
  static StringArray* Create(const void* data, const StringOffsets& soffsets,
                             int* pbytes = nullptr);

  int count() const { return m_count; }
  const char* base() const;
  int offset(int index) const;
  int bytes() const;
  const char* field(int index) const;
  const char* field(kIssuerInfo index) const;
  bool check(const void* data, const StringOffsets& soffsets) const;
};

typedef struct _tag_QBISSUERINFO {
  char Institution_Code[7 + 1];  // 发行人代码
  char Full_Name_C[80 + 1];      // 发行机构全称
  // char Jianpin[256];				//机构名称简拼
  // char Quanpin[256];				//机构名称全拼
  char Issuer_Type[16 + 1];              // 机构类型
  char SW_Sector_Code[16 + 1];           // 一级行业代码
  char SW_Subsector_Code[16 + 1];        // 二级行业代码
  char SW_2021_Sector_Code[16 + 1];      // 2021版申万行业一级代码
  char SW_2021_Subsector_Code[16 + 1];   // 2021版申万行业二级代码
  char Province_Code[16 + 1];            // 区域代码
  char Short_Name_C[80 + 1];             // 中文简称
  char Full_Name_E[256 + 1];             // 英文全称
  char Short_Name_E[80 + 1];             // 英文简称
  char Listed_Type[15 + 1];              // 上市公司
  char Actual_Controller_Name[128 + 1];  // 实际控制人
  char Actual_Controller_Type[16 + 1];   // 实际控制人类型
  char Rate[10 + 1];                     // 评级
  char CBRC_Financing_Platform[8];  // 银监会投融资平台，Y = 平台债
  char Municipal_code[16 + 1];      // 市区级
  char Issuer_tag[10];              // 主体信息
} QBISSUERINFO;
typedef StringArray IssuerInfo;
#define ISSUER_FIELD(PISSUER_INFO, KISSUER_INFO) \
  PISSUER_INFO->field((int)kIssuerInfo::KISSUER_INFO)
class S_BONDLIB_EXPORT IssuerStringOffsets : public StringOffsets {
 public:
  IssuerStringOffsets();
  void Add(int off, int size) {
    this->emplace_back(qb::base::strinfo{off, size});
  }
  static IssuerStringOffsets& Get();
};

// class IssueObjectMap;
class CQBIssuerInfo;
class S_BONDLIB_EXPORT FilterHelper {
 public:
  void AddKeys(const std::string& source, const std::string& split);
  void Filter(CQBIssuerInfo& source, CQBIssuerInfo& target);

 private:
  std::set<std::string> m_keys;
};

class S_BONDLIB_EXPORT CQBIssuerInfo {
 public:
  typedef qb::base::KeyString KeyString;
  typedef std::map<KeyString, IssuerInfo*> IssuerInfoMap;
  typedef std::vector<std::string> IssuerInfoList;

  static CQBIssuerInfo& instance();
  static CQBIssuerInfo& MainUnderwriterContainer();
  static CQBIssuerInfo& ABSBondSeries();
  static CQBIssuerInfo& ABSBondFinancier();
  static CQBIssuerInfo& GuarantorInstitution();

 public:
  const IssuerInfoMap& GetAllIssuerInfo() const { return m_map; }
  IssuerInfoMap& GetAllIssuerInfo() { return m_map; }
  const IssuerInfo* GetIssuerInfo(const std::string& id);
  const IssuerInfo* GetIssuerInfoByIndex(int index);
  int GetIndexByIssuerCode(const char* sCode);
  int GetAllIssuerCount();

  bool Clear();
  bool Add(const QBISSUERINFO& info);
  bool Add(const QBISSUERINFO& info, int order);
  void FinishUpdate();
  int GetStateId();
  int GetLastOrder();

  std::mutex& GetMutex() { return m_mutex; }

 public:
  void DumpStatus(int mode = 0) const;
  FilterHelper m_filterHelper;

 private:
  CQBIssuerInfo();
  virtual ~CQBIssuerInfo();

 protected:
  IssuerInfoMap m_map;
  IssuerInfoList m_list;
  std::mutex m_mutex;
  int m_stateid;
  int m_lastorder;
};
